package com.qiaofang.housewarehouse.dao.impl;

import com.alibaba.fastjson.JSONObject;
import com.qiaofang.housewarehouse.base.util.ArraySelfUtils;
import com.qiaofang.housewarehouse.dao.EsDAO;
import com.qiaofang.housewarehouse.dao.domain.IndexCityRegionDistrict;
import com.qiaofang.housewarehouse.dao.elasticsearch.EsClient;
import com.qiaofang.housewarehouse.dao.utils.ConfigUtils;
import com.qiaofang.housewarehouse.dao.utils.DateUtils;
import com.qiaofang.housewarehouse.stub.bean.SaleAndRentalByCityDTO;
import com.qiaofang.housewarehouse.stub.constants.HouseTypeEnum;
import com.qiaofang.housewarehouse.stub.constants.TableConstants;
import io.netty.util.internal.StringUtil;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Repository
public class EsDaoImpl implements EsDAO {
    private static final Logger logger = LoggerFactory.getLogger(EsDaoImpl.class);

    @Override
    public SearchResponse searchHouseList(Map<String, String> paramMap) throws Exception {
        int offset = 0;
        int size = 50;
        if (!StringUtil.isNullOrEmpty(paramMap.get("pageSize"))) {
            size = Integer.valueOf(paramMap.get("pageSize"));
        }
        if (!StringUtil.isNullOrEmpty(paramMap.get("pageIndex"))) {
            offset = (Integer.valueOf(paramMap.get("pageIndex")) - 1) * size;
        }
        QueryBuilder queryBuilder = QueryBuilders.boolQuery();
        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            if (StringUtil.isNullOrEmpty(value) || "pageSize".equals(key) || "pageIndex".equals(key) || "indexName".equals(key) || "typeName".equals(key)) {
                continue;
            }
            Float floatEnd = Float.valueOf("999999999");
            Integer integerEnd = Integer.valueOf("999999999");
            if ("rentPriceRange".equals(key)) {
                String[] split = value.split("~");
                Float start = Float.valueOf(split[0]);
                Float end = Float.valueOf(split[1]);
                ((BoolQueryBuilder) queryBuilder).must(QueryBuilders.rangeQuery("rentPriceR").gte(start).lte((end != 0) ? end : floatEnd));
            } else if ("sellPriceRange".equals(key)) {
                String[] split = value.split("~");
                Float start = Float.valueOf(split[0]);
                Float end = Float.valueOf(split[1]);
                ((BoolQueryBuilder) queryBuilder).must(QueryBuilders.rangeQuery("sellPriceR").gte(start).lte((end != 0) ? end : floatEnd));
            } else if ("roomAreaRange".equals(key)) {
                String[] split = value.split("~");
                Float start = Float.valueOf(split[0]);
                Float end = Float.valueOf(split[1]);
                ((BoolQueryBuilder) queryBuilder).must(QueryBuilders.rangeQuery("roomAreaR").gte(start).lte((end != 0) ? end : floatEnd));
            } else if ("yearRange".equals(key)) {
                String[] split = value.split("~");
                Integer start = Integer.valueOf(split[0]);
                Integer end = Integer.valueOf(split[1]);
                ((BoolQueryBuilder) queryBuilder).must(QueryBuilders.rangeQuery("yearR").gte(start).lte((end != 0) ? end : integerEnd));
            } else if ("floorRange".equals(key)) {
                String[] split = value.split("~");
                Integer start = Integer.valueOf(split[0]);
                Integer end = Integer.valueOf(split[1]);
                ((BoolQueryBuilder) queryBuilder).must(QueryBuilders.rangeQuery("floorR").gte(start).lte((end != 0) ? end : integerEnd));
            } else if ("houseType".equals(key)) {
                Float houseType = Float.valueOf(value);
                if (houseType.equals(Float.valueOf(HouseTypeEnum.FIVE.getValue()))) {
                    ((BoolQueryBuilder) queryBuilder).must(QueryBuilders.rangeQuery("houseTypeR").gte(houseType));
                } else {
                    ((BoolQueryBuilder) queryBuilder).must(QueryBuilders.termQuery("houseTypeR", houseType));
                }
            } else if ("keywords".equals(key)) {
                ((BoolQueryBuilder) queryBuilder).must(QueryBuilders.wildcardQuery("estate", "*" + value + "*"));
            } else if ("estates".equals(key)) {
                String[] values = value.split(",");
                Object[] subAry = ArraySelfUtils.splitAry(values, 1024);
                for (Object obj : subAry) {
                    String[] aryItem = (String[]) obj;
                    ((BoolQueryBuilder) queryBuilder).must(QueryBuilders.termsQuery("estate", aryItem));
                }
            } else if ("contactMobiles".equals(key)) {
                String[] values = value.split(",");
                Object[] subAry = ArraySelfUtils.splitAry(values, 1024);
                //黑名单的数据不过滤调
                /*for (Object obj : subAry) {
                    String[] aryItem = (String[]) obj;
                    ((BoolQueryBuilder) queryBuilder).mustNot(QueryBuilders.termsQuery("contactMobile", aryItem));
                }*/
            }else if("collectionTime".equals(key)){
                ((BoolQueryBuilder) queryBuilder).must(QueryBuilders.rangeQuery("publishTime").lte(value));
                ((BoolQueryBuilder) queryBuilder).must(QueryBuilders.rangeQuery("createTime").lte(value));
            }else if("ids".equals(key)){
                String[] values = value.split(",");
                Object[] subAry = ArraySelfUtils.splitAry(values, 1024);
                for (Object obj : subAry) {
                    String[] aryItem = (String[]) obj;
                    ((BoolQueryBuilder) queryBuilder).must(QueryBuilders.termsQuery("_id", aryItem));
                }
            }else if ("sources".equals(key)) {
                String[] values = value.split(",");
                Object[] subAry = ArraySelfUtils.splitAry(values, 1024);
                for (Object obj : subAry) {
                    String[] aryItem = (String[]) obj;
                    ((BoolQueryBuilder) queryBuilder).must(QueryBuilders.termsQuery("source", aryItem));
                }
            }  else {
                ((BoolQueryBuilder) queryBuilder).must(QueryBuilders.wildcardQuery(key, "*" + value + "*"));
            }
        }
        logger.info("查询语句为：{}", queryBuilder.toString());
        SearchResponse searchResponse = EsClient.queryData(paramMap.get("indexName"), paramMap.get("typeName"), queryBuilder, offset, size);
        return searchResponse;
    }

    @Override
    public SearchResponse searchHouseNoPageList(Map<String, String> paramMap) throws Exception {
        QueryBuilder queryBuilder = QueryBuilders.boolQuery();
        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            if (StringUtil.isNullOrEmpty(value) || "indexName".equals(key) || "typeName".equals(key)) {
                continue;
            }
            if ("dateRange".equals(key)) {
                String[] split = value.split("~");
                ((BoolQueryBuilder) queryBuilder).must(QueryBuilders.rangeQuery("createTime").gte(split[0]).lte(split[1]));
            } else {
                ((BoolQueryBuilder) queryBuilder).must(QueryBuilders.wildcardQuery(key, "*" + value + "*"));
            }
        }
        logger.info("查询语句为：{}", queryBuilder.toString());
        SearchResponse searchResponse = EsClient.queryDataNoPage(paramMap.get("indexName"), paramMap.get("typeName"), queryBuilder);
        return searchResponse;
    }

    @Override
    public GetResponse getIndexById(Map<String, String> paramMap) throws Exception {
        logger.info("查询id为：{}", paramMap.get("id"));
        GetResponse reponse = EsClient.getIndexById(paramMap.get("indexName"), paramMap.get("typeName"), paramMap.get("id"));
        return reponse;
    }

    /**
     * 根据城市名称获取区域列表
     *
     * @param cls        javabean.class
     * @param index      索引
     * @param type       类型
     * @param cityName   城市名称
     * @param <T>
     * @return
     */
    @Override
    public <T> List<T> searchRegionListByCityType(Class<T> cls, String index, String type, String cityName) {
        List<T> clsList = new ArrayList<>();
        QueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .filter(QueryBuilders.hasParentQuery("city", QueryBuilders.termQuery("name", cityName), false));
        List<JSONObject> jsonObjectList = EsClient.searchSearchResponseByQueryBuilder(index, type, queryBuilder, null);
        for (JSONObject jsonObject : jsonObjectList) {
            clsList.add(JSONObject.parseObject(jsonObject.toJSONString(), cls));
        }
        return clsList;
    }
    @Override
    public <T> List<T> searchDistrictListByCityAndRegionType(Class<T> cls, String index, String type, String cityName, String regionName) {
        List<T> clsList = new ArrayList<>();
        QueryBuilder queryBuilder2 = QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("name", regionName))
                .must(QueryBuilders.hasParentQuery("city", QueryBuilders.termQuery("name", cityName), false));
        QueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .filter(QueryBuilders.hasParentQuery("region",queryBuilder2,false));
        List<JSONObject> jsonObjectList = EsClient.searchSearchResponseByQueryBuilder(index, type, queryBuilder, null);
        for (JSONObject jsonObject : jsonObjectList) {
            clsList.add(JSONObject.parseObject(jsonObject.toJSONString(), cls));
        }
        return clsList;
    }

    /**
     * 根据城市获取出租和出售情况
     * @param cityName
     * @return
     */
    @Override
    public SaleAndRentalByCityDTO querySaleAndRentalByCity(String cityName)throws Exception {
        //历史出租出售
        SaleAndRentalByCityDTO saleAndRentalByCityDTO = new SaleAndRentalByCityDTO();
        QueryBuilder queryBuilderRental = QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("city", cityName));
        SearchResponse searchResponseRental = EsClient.queryDataNoCondition(ConfigUtils.getIndexHswhRentalHouse(), TableConstants.INDEX_TYPE_RENTAL_HOUSE, queryBuilderRental);

        QueryBuilder queryBuilderSale = QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("city", cityName));
        SearchResponse searchResponseSale = EsClient.queryDataNoCondition(ConfigUtils.getIndexHswhSaleHouse(), TableConstants.INDEX_TYPE_SALE_HOUSE, queryBuilderSale);

        //当天出租出售
        QueryBuilder queryBuilderRentalToday = QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("city", cityName))
                .must(QueryBuilders.rangeQuery("createTime").gte(DateUtils.getDayStartTime()))
                .must(QueryBuilders.rangeQuery("createTime").lte(DateUtils.getDayEndTime()));
        SearchResponse searchResponseRentalToday = EsClient.queryDataNoCondition(ConfigUtils.getIndexHswhRentalHouse(), TableConstants.INDEX_TYPE_RENTAL_HOUSE, queryBuilderRentalToday);

        QueryBuilder queryBuilderSaleToday = QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("city", cityName))
                .must(QueryBuilders.rangeQuery("createTime").gte(DateUtils.getDayStartTime()))
                .must(QueryBuilders.rangeQuery("createTime").lte(DateUtils.getDayEndTime()));
        SearchResponse searchResponseSaleToday = EsClient.queryDataNoCondition(ConfigUtils.getIndexHswhSaleHouse(), TableConstants.INDEX_TYPE_SALE_HOUSE, queryBuilderSaleToday);

        saleAndRentalByCityDTO.setNewHouseRentalNum(searchResponseRentalToday.getHits().getTotalHits());
        saleAndRentalByCityDTO.setNewHouseSaleNum(searchResponseSaleToday.getHits().getTotalHits());
        saleAndRentalByCityDTO.setNewHouseNum(saleAndRentalByCityDTO.getNewHouseRentalNum()+saleAndRentalByCityDTO.getNewHouseSaleNum());
        saleAndRentalByCityDTO.setAllHouseRentalNum(searchResponseRental.getHits().getTotalHits());
        saleAndRentalByCityDTO.setAllHouseSaleNum(searchResponseSale.getHits().getTotalHits());
        saleAndRentalByCityDTO.setAllHouseNum(saleAndRentalByCityDTO.getAllHouseRentalNum()+saleAndRentalByCityDTO.getAllHouseSaleNum());

        return saleAndRentalByCityDTO;
    }
}
